{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mist.jpg\n",
      "[[0.24631618 0.24631618 0.244837   ... 0.41477935 0.41043809 0.41080386]\n",
      " [0.24631618 0.24631618 0.244837   ... 0.41477935 0.41043809 0.41080386]\n",
      " [0.24595633 0.24595633 0.24343352 ... 0.43133447 0.4267494  0.42726282]\n",
      " ...\n",
      " [0.81214338 0.81214338 0.80797325 ... 0.19562184 0.19817051 0.19143364]\n",
      " [0.80885232 0.80885232 0.80433664 ... 0.21233978 0.21605122 0.20939245]\n",
      " [0.81041148 0.81041148 0.80528509 ... 0.21817983 0.22231612 0.21625595]]\n",
      "[[0.24631618 0.24631618 0.244837   ... 0.41099514 0.41043809 0.41080386]\n",
      " [0.24631618 0.24631618 0.244837   ... 0.41099514 0.41043809 0.41080386]\n",
      " [0.24595633 0.24595633 0.24343352 ... 0.42762032 0.4267494  0.42726282]\n",
      " ...\n",
      " [0.79818515 0.79818515 0.79426286 ... 0.19271786 0.19662593 0.18969595]\n",
      " [0.79200121 0.79200121 0.78768535 ... 0.21040499 0.21519226 0.20816645]\n",
      " [0.79257034 0.79257034 0.78740738 ... 0.21711524 0.22232774 0.21582444]]\n",
      "[[0.24631618 0.24631618 0.244837   ... 0.41185227 0.41043809 0.41080386]\n",
      " [0.24631618 0.24631618 0.244837   ... 0.41185227 0.41043809 0.41080386]\n",
      " [0.24595633 0.24595633 0.24343352 ... 0.42846511 0.4267494  0.42726282]\n",
      " ...\n",
      " [0.79733614 0.79733614 0.79333846 ... 0.18957342 0.19378058 0.18709867]\n",
      " [0.79151913 0.79151913 0.78714023 ... 0.20314383 0.20836832 0.20212429]\n",
      " [0.79234344 0.79234344 0.78714629 ... 0.20635304 0.21205542 0.20654538]]\n",
      "12.5074533\n"
     ]
    }
   ],
   "source": [
    "import cv2,math\n",
    "import numpy as np\n",
    "\n",
    " \n",
    " \n",
    " \n",
    "def guideFilter(I, p, winSize, eps):\n",
    "    \"\"\"\n",
    "    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，均值平滑窗口半径 r，正则化参数 e。\n",
    "    利用导向滤波进行图像平滑处理时，通常令p=I。\n",
    "    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。\n",
    "    :param I:\n",
    "    :param p:\n",
    "    :param winSize:\n",
    "    :param eps:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    # I的均值平滑\n",
    "    mean_I = cv2.blur(I, winSize)\n",
    "    # p的均值平滑\n",
    "    mean_p = cv2.blur(p, winSize)\n",
    "    # I*I和I*p的均值平滑\n",
    "    mean_II = cv2.blur(I * I, winSize)\n",
    "    mean_Ip = cv2.blur(I * p, winSize)\n",
    "    # 方差\n",
    "    var_I = mean_II - mean_I * mean_I  # 方差公式\n",
    "    # 协方差\n",
    "    cov_Ip = mean_Ip - mean_I * mean_p\n",
    "    a = var_I / (var_I + eps)\n",
    "    print(a)\n",
    "    b = mean_p - a * mean_I\n",
    "    # 对a、b进行均值平滑\n",
    "    mean_a = cv2.blur(a, winSize)\n",
    "    mean_b = cv2.blur(b, winSize)\n",
    "    q = mean_a * I + mean_b\n",
    "    return q\n",
    " \n",
    "\n",
    "def FastguideFilter(I, p, winSize, eps, s):\n",
    "    \"\"\"\n",
    "    快速导向滤波\n",
    "    通过下采样减少像素点，计算mean_a & mean_b后进行上采样恢复到原有的尺寸大小。\n",
    "    假设缩放比例为s,那么缩小后像素点的个数为N/s^2，那么时间复杂度变为O(N/s^2)\n",
    "    fmean代表均值平滑，fsubsample代表图像下采样即缩小图像，fupsample代表图片上采样即放大图像，s为缩小系数。\n",
    "    :param I:\n",
    "    :param p:\n",
    "    :param winSize:\n",
    "    :param eps:\n",
    "    :param s:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    # 输入图像的高、宽\n",
    "    h, w = I.shape[:2]\n",
    " \n",
    "    # 缩小图像\n",
    "    size = (int(round(w * s)), int(round(h * s)))\n",
    " \n",
    "    small_I = cv2.resize(I, size, interpolation=cv2.INTER_CUBIC)\n",
    "    small_p = cv2.resize(I, size, interpolation=cv2.INTER_CUBIC)\n",
    " \n",
    "    # 缩小滑动窗口\n",
    "    X = winSize[0]\n",
    "    small_winSize = (int(round(X * s)), int(round(X * s)))\n",
    " \n",
    "    # I的均值平滑\n",
    "    mean_small_I = cv2.blur(small_I, small_winSize)\n",
    " \n",
    "    # p的均值平滑\n",
    "    mean_small_p = cv2.blur(small_p, small_winSize)\n",
    " \n",
    "    # I*I和I*p的均值平滑\n",
    "    mean_small_II = cv2.blur(small_I * small_I, small_winSize)\n",
    " \n",
    "    mean_small_Ip = cv2.blur(small_I * small_p, small_winSize)\n",
    " \n",
    "    # 方差\n",
    "    var_small_I = mean_small_II - mean_small_I * mean_small_I  # 方差公式\n",
    " \n",
    "    # 协方差\n",
    "    cov_small_Ip = mean_small_Ip - mean_small_I * mean_small_p\n",
    " \n",
    "    small_a = cov_small_Ip / (var_small_I + eps)\n",
    "    small_b = mean_small_p - small_a * mean_small_I\n",
    " \n",
    "    # 对a、b进行均值平滑\n",
    "    mean_small_a = cv2.blur(small_a, small_winSize)\n",
    "    mean_small_b = cv2.blur(small_b, small_winSize)\n",
    " \n",
    "    # 放大\n",
    "    size1 = (w, h)\n",
    "    mean_a = cv2.resize(mean_small_a, size1, interpolation=cv2.INTER_LINEAR)\n",
    "    mean_b = cv2.resize(mean_small_b, size1, interpolation=cv2.INTER_LINEAR)\n",
    " \n",
    "    q = mean_a * I + mean_b\n",
    " \n",
    "    return q\n",
    " \n",
    "\"\"\"\n",
    "下图导向滤波采用了r=16也就是winSize=(16,16), eps=0.01的参数大小。  \n",
    "快速导向滤波采用了r=16也就是winSize=(16,16), eps=0.01，s=0.5的参数大小。\n",
    "\"\"\"\n",
    "def run():\n",
    "    name = input()\n",
    "    image = cv2.imread(name, cv2.IMREAD_ANYCOLOR)\n",
    "    #将图像归一化\n",
    "    image_0_1 = image/255.0\n",
    " \n",
    "    #导向滤波(三通道)\n",
    "    b, g, r = cv2.split(image_0_1)\n",
    "    # 1.753212477\n",
    "    gf1 = guideFilter(b, b, (16,16), math.pow(0.1,2))\n",
    "    gf2 = guideFilter(g, g, (16,16), math.pow(0.1,2))\n",
    "    gf3 = guideFilter(r, r, (16,16), math.pow(0.1,2))\n",
    "    # 0.944390349\n",
    "#     gf1 = FastguideFilter(b, b, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "#     gf2 = FastguideFilter(g, g, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "#     gf3 = FastguideFilter(r, r, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "    gf = cv2.merge([gf1, gf2, gf3])\n",
    " \n",
    " \n",
    "    #保存导向滤波结果\n",
    "    gf = gf*255\n",
    "    gf[gf>255] = 255\n",
    "    gf = np.round(gf)\n",
    "    gf = gf.astype(np.uint8)\n",
    "    res = np.hstack((image,gf))\n",
    "    cv2.imshow(\"res\",res)\n",
    "    cv2.imwrite(r'a.jpg', gf)\n",
    "    cv2.waitKey(0)\n",
    " \n",
    "\n",
    " \n",
    "def costtime(func):\n",
    "    # time start\n",
    "    t1 = cv2.getTickCount()\n",
    "    func()\n",
    "    # time end\n",
    "    t2 = cv2.getTickCount()\n",
    " \n",
    "    # 计算执行秒数,利用getTickFrequency()获取时钟频率\n",
    "    t = (t2 - t1) / cv2.getTickFrequency()\n",
    "    print(t)\n",
    " \n",
    " \n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    # costtime(gpu_run)\n",
    "    costtime(run)\n",
    " \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "mist.png\n",
      "(492, 752, 3)\n",
      "0.1165444\n"
     ]
    }
   ],
   "source": [
    " \n",
    "def guideFilter(I, p, winSize, eps):\n",
    "    \"\"\"\n",
    "    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，均值平滑窗口半径 r，正则化参数 e。\n",
    "    利用导向滤波进行图像平滑处理时，通常令p=I。\n",
    "    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。\n",
    "    :param I:\n",
    "    :param p:\n",
    "    :param winSize:\n",
    "    :param eps:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    \n",
    "    sqaure_avg = cv2.blur(p * p, winSize)\n",
    "    avg = cv2.blur(p, winSize)\n",
    "    \n",
    "    ak = (sqaure_avg - avg ** 2)/(sqaure_avg - avg **2 + eps)\n",
    "    bk = (-1 * ak + 1) * avg\n",
    "    \n",
    "    a = cv2.blur(ak, winSize)\n",
    "    b = cv2.blur(bk, winSize)\n",
    "    \n",
    "    q = a * p + b\n",
    "    \n",
    "    return q\n",
    "\n",
    "def fastGuideFilter(I, p, winSize, eps, s):\n",
    "    \"\"\"\n",
    "    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，正则化参数 eps。\n",
    "    利用导向滤波进行图像平滑处理时，通常令p=I。\n",
    "    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。\n",
    "    :param I:\n",
    "    :param p:\n",
    "    :param winSize:\n",
    "    :param eps:\n",
    "    :return:\n",
    "    \"\"\"\n",
    "    \n",
    "    sp = cv2.resize(p, None, fx=s, fy=s)\n",
    "    \n",
    "    \n",
    "    sqaure_avg = cv2.blur(sp * sp, winSize)\n",
    "    avg = cv2.blur(sp, winSize)\n",
    "    \n",
    "    ak = (sqaure_avg - avg ** 2)/(sqaure_avg - avg **2 + eps)\n",
    "    bk = (-1 * ak + 1) * avg\n",
    "    \n",
    "    a = cv2.blur(ak, winSize)\n",
    "    b = cv2.blur(bk, winSize)\n",
    "    \n",
    "    bigA = cv2.resize(a, None, fx=2, fy=2)\n",
    "    bigB = cv2.resize(b, None, fx=2, fy=2) \n",
    "    q = bigA * p + bigB\n",
    "    \n",
    "    return q\n",
    "\n",
    "\"\"\"\n",
    "下图导向滤波采用了r=16也就是winSize=(16,16), eps=0.01的参数大小。  \n",
    "快速导向滤波采用了r=16也就是winSize=(16,16), eps=0.01，s=0.5的参数大小。\n",
    "\"\"\"\n",
    "def run():\n",
    "    name = input()\n",
    "    image = cv2.imread(name, cv2.IMREAD_ANYCOLOR)\n",
    "    #将图像归一化\n",
    "    \n",
    "    # time start\n",
    "    t1 = cv2.getTickCount()\n",
    "    image_0_1 = image/255.0\n",
    " \n",
    "    #导向滤波(三通道)\n",
    "    b, g, r = cv2.split(image_0_1)\n",
    "    gf1 = guideFilter(b, b, (16,16), math.pow(0.1,2))\n",
    "    gf2 = guideFilter(g, g, (16,16), math.pow(0.1,2))\n",
    "    gf3 = guideFilter(r, r, (16,16), math.pow(0.1,2))\n",
    "\n",
    "#     gf1 = FastguideFilter(b, b, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "#     gf2 = FastguideFilter(g, g, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "#     gf3 = FastguideFilter(r, r, (16, 16), math.pow(0.1, 2),s=0.5)\n",
    "    gf = cv2.merge([gf1, gf2, gf3])\n",
    " \n",
    "    print(gf.shape)\n",
    " \n",
    "    \n",
    "    \n",
    "    \n",
    "\n",
    "    #保存导向滤波结果\n",
    "    gf = gf*255\n",
    "    gf[gf>255] = 255\n",
    "    gf = np.round(gf)\n",
    "    gf = gf.astype(np.uint8)\n",
    "    res = np.hstack((image,gf))\n",
    "    \n",
    "    # time end\n",
    "    t2 = cv2.getTickCount()\n",
    " \n",
    "    # 计算执行秒数,利用getTickFrequency()获取时钟频率\n",
    "    t = (t2 - t1) / cv2.getTickFrequency()\n",
    "    print(t)\n",
    "    \n",
    "    cv2.imshow(\"res\",res)\n",
    "    cv2.waitKey(0)\n",
    "    return gf\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "gf = run()\n",
    " "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [],
   "source": [
    "## dehaze\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "def darkChannel(p, winSize):\n",
    "    minChannel = p.min(axis=2)\n",
    "    \n",
    "    shape = cv2.MORPH_RECT\n",
    "    kernel = cv2.getStructuringElement(shape, winSize)\n",
    "    min_image = cv2.erode(minChannel, kernel)\n",
    "    return min_image\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [],
   "source": [
    "def largest_indices(ary, n):\n",
    "    \"\"\"Returns the n largest indices from a numpy array.\"\"\"\n",
    "    flat = ary.flatten()\n",
    "    indices = np.argpartition(flat, -n)[-n:]\n",
    "    indices = indices[np.argsort(-flat[indices])]\n",
    "    return np.unravel_index(indices, ary.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "def CalculateA(p, winSize):\n",
    "    \n",
    "    dark_p = darkChannel(p, winSize)\n",
    "    \n",
    "    h, w = dark_p.shape\n",
    "    top_pixels = h * w // 1000\n",
    "    \n",
    "    indexs = largest_indices(dark_p, top_pixels)\n",
    "    \n",
    "    A = p[indexs].max(axis=0)\n",
    "    \n",
    "    return A\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "def CalculateTx(p, winSize,w=0.95):\n",
    "    \n",
    "    A = CalculateA(p,winSize)\n",
    "    \n",
    "    dark_t = darkChannel(p / A,winSize)\n",
    "    \n",
    "    t = 1 - w * dark_t\n",
    "    \n",
    "    return t\n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [],
   "source": [
    "def MistRemove(p, winSize,t0):\n",
    "    \n",
    "    A = CalculateA(p,winSize)\n",
    "    \n",
    "    p=p/255\n",
    "    dark_p = darkChannel(p,winSize)\n",
    "    \n",
    "    b, g, r = cv2.split(p)\n",
    "    gf1 = guideFilter(b, dark_p, winSize, math.pow(0.1,2))\n",
    "    gf2 = guideFilter(g, dark_p, winSize, math.pow(0.1,2))\n",
    "    gf3 = guideFilter(r, dark_p, winSize, math.pow(0.1,2))\n",
    "    \n",
    "#     gf1 = FastguideFilter(b, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "#     gf2 = FastguideFilter(g, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "#     gf3 = FastguideFilter(r, tx, winSize, math.pow(0.1,2),s=0.5)\n",
    "\n",
    "    gf = cv2.merge([gf1, gf2, gf3])\n",
    "    \n",
    "    gf = gf*255\n",
    "    gf[gf>255] = 255\n",
    "    gf = np.round(gf)\n",
    "    gf = gf.astype(np.uint8)\n",
    "    \n",
    "    t = 1 - gf * 0.95 / A\n",
    "    \n",
    "    \n",
    "    \n",
    "    t = cv2.max(t, t0)\n",
    "    \n",
    "   \n",
    "    \n",
    "\n",
    "    rows, cols, channels = gf.shape\n",
    "    \n",
    "    a = np.average(A)\n",
    "    o=((p - a)/t + a)\n",
    "    \n",
    "    o = np.round(o)\n",
    "    \n",
    "    return a,p,t\n",
    "    \n",
    "    \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [],
   "source": [
    "p = cv2.imread(\"mist.jpg\")\n",
    "a,p,t = MistRemove(p,(16,16), 0.1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "p = cv2.imread(\"mist.jpg\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "27"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "o = (p -a)/t+a\n",
    "o = np.round(o)\n",
    "o = o.astypes(\"uint8\")\n",
    "cv2.imshow('1',o)\n",
    "cv2.waitKey(0)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
